/* user.c : User processes
 */

#include <xeroskernel.h>

static unsigned int prod,con,rootpid;

void zombietask( void );
// void root2(void);
void sig1(void);
void sig2(void);
void sig3(void);
void sig4(void);
void sig5(void);
void sig18(void);
void a3Proc(void);

/* Your code goes here */
 void producer( void ) {
/****************************/

    int         i, res;
    res = -99;
    void (** oldHandler)(void *);
    void (** oldHandler2)(void *);
    void (** oldHandler3)(void *);
    res = syssighandler(2,sig1,oldHandler);
        kprintf("## pro res: %d ###\n",res);
    res = syssighandler(1,sig2,oldHandler2);
        kprintf("## pro res: %d ###\n",res);
    res = syssighandler(0,sig3,oldHandler3);
        kprintf("## pro res: %d ###\n",res);

    for( i = 0; i < 10; i++ ) {
        kprintf( "Produce %d: ", i );
        res = syssigwait();
        kprintf("## pEnd res: %d ###\n",res);
    }
}

 void consumer( void ) {
/****************************/

    int         i, size;
    for( i = 0; i < 10; i++ ) {
        kprintf( "Consume %d \n", i );
        syssleep(2000);
    }

}

void a3Proc(void){ 
	kprintf("signaling 20 in a3Proc\n");
	int ret = syskill(rootpid, 20);
	kprintf("ret = %d\n",ret);
	kprintf("signaling 18 in a3Proc\n");
	ret = syskill(rootpid, 18);
	kprintf("ret = %d\n",ret);
	sysstop();
}

void a3Proc2(void){
	syssleep(5000);
	syskill(rootpid, 18);
}

void a3Proc3(void){
	syssleep(5000);
	kprintf("signalling 20 in a3Proc3\n");
	syskill(rootpid, 20);
}

void sig1() {
    sysputs("\nBad Boi!\n");
}

void sig2() {
    sysputs("\nDon't swear, \n");
}

void sig3() {
    sysputs("\nI have to go to school\n");
}

void sig18(){
	sysputs("\nSomeone called signal 18?\n");
}

void sig18_2(){
	sysputs("\nSomeone called a replacement 18?\n");
}

 void     root2( void ) {
/****************************/
void (** oldHandler)(void *);
    int i,size;
    i = sysgetpid();
    kprintf("Root %d has been called\n",i);

    sysyield();
    sysyield();
    prod = syscreate( &producer, 4096 );
    // con = syscreate( &consumer, 4096 );
    syssleep(2000);
        // size = syskill(5,1);
        // kprintf("killing 5,1: Rresults: %d\n",size);
    for( i=0;i<10;i++ ) {
        // syssleep(5000);
        kprintf("killing %d, %d",prod,i);
        size = syskill(prod,i);
        kprintf(" ..Rresults: %d\n",size);
    }
    syssleep(8000);
    kprintf("Root completed..\n");

}

void testsyscalls(void){
	int fd, ret;
	char buf[128];
	char *str=buf;
	//sysopen with invalid param
	kprintf("opening device 3\n");
	fd = sysopen(3);
	kprintf("resulting file descriptor: %d\n",fd);
	//syswrite with invalid fd
	kprintf("writing to invalid fd\n");
	ret = syswrite(5, str, 5);
	kprintf("result: %d\n",ret);
	//sysioctl for invalid commands
	syssleep(5000);
	kprintf("sysioctl for invalid commands\n");
	fd = sysopen(KEYBOARD);
	ret = sysioctl(fd, 99);
	kprintf("result: %d\n",ret);
	//sysread to read less than buffer length
	kprintf("read less characters than buffer length\n");
	ret = sysread(fd,str,1);
	kprintf("Result: %d\n", ret);
	//2 other test case??
	//valid ioctl
	kprintf("ioctl for valid commands\n");
	ret = sysioctl(fd,49);
	kprintf("Result: %d\n", ret);
	//close invalid device
	kprintf("close an invalid device\n");
	ret = sysclose(5);
	kprintf("Result: %d\n",ret);
}

void root(void){
	int fd1, fd2, fd3, ret;
	char buff[128];
	char *str = buff;
	void (** oldHandler)(void *);
	//syssleep(10000);
	//prints greeting
	kprintf("root says hello\n");
	//opens echo keyboard
	kprintf("opening echo keyboard\n");
	fd1 = sysopen(KEYBOARD);
	kprintf("results: %d\n",fd1);
	//reads characters 1 at a time for 10 times
	int i;
	for(i=0; i<10; i++){
		kprintf("\nreading 1 character at a time, i = %d\n",i);
		ret = sysread(fd1,str,1);
	}
	//opens no echo keyboard
	kprintf("opening non echo keyboard\n");
	fd2 = sysopen(CONSOLE);
	kprintf("results: %d\n",fd2);
	//opens echo keyboard
	kprintf("reopening echo keyboard\n");
	fd3 = sysopen(KEYBOARD);
	kprintf("results: %d\n",fd3);
	//closes the keyboard
	kprintf("closing keyboards\n");
	ret = sysclose(fd2);
	ret = sysclose(fd1);
	//open "no echo"
	kprintf("opening no echo keyboard again\n");
	fd1 = sysopen (CONSOLE);
	kprintf("reading 3 lines of 10 characters...\nPlease input 3 lines of more than 10 characters\n");
	for(i=0; i<3; i++){
		ret = sysread(fd1,str,10);
		kprintf("str = %s\n",str);
	}	
	kprintf("press ctrl-d\n");
	while(1){
		ret = sysread(fd1,str,10);
		if(ret == 0)
			break;
	}
	kprintf("closing no echo keyboard\n");
	ret = sysclose(fd1);
	//open "echo"
	rootpid = sysgetpid();
	kprintf("Reopening echo keyboard\n");
	fd1 = sysopen(KEYBOARD);
	kprintf("Installing signal 18\n");
	ret = syssighandler(18,sig18,&oldHandler);
	kprintf("Creating a3Proc\n");
	syscreate(&a3Proc, 4096);
	kprintf("trying to read\n");
	ret = sysread(fd1, str, 10);
	if(ret == -1){
		kprintf("read was interrupted\n");
	}
	
	kprintf("Creating a3Proc2\n");
	syscreate(&a3Proc2, 4096);
	kprintf("Reinstalling signal 18\n");
	syssighandler(18, sig18_2, &oldHandler);
	ret = sysread(fd1, str, 10);
	if(ret == -1){
		kprintf("2nd read was interrupted\n");
	}

	kprintf("Installing signal 20\n");
	ret = syssighandler(20, (void *)oldHandler, NULL);
	kprintf("Creating a3Proc3\n");
	syscreate(&a3Proc3,4096);
	ret = sysread(fd1, str, 10);
	if(ret == -1){
		kprintf("3rd read was interrupted\n");
	}

	kprintf("press ctrl-d\n");
	while(1){
		ret = sysread(fd1, str, 10);
		if(ret == 0)
			break; 
	}
	ret = sysread(fd1, str, 10);
	kprintf("Attempting last read...\nReturned value: %d\n",ret);

	kprintf("Root ends\n");
}

 void     root_a2( void ) {
/****************************/

    int i;
    unsigned int p[4];
    char str[40];
    char *msg = str;
    sysputs("Root IS ALIIIIIIIVE!\n");

	kprintf("child pid: ");
    for( i=0; i<4 ; i++ ) {
        p[i] = syscreate(&zombietask, 4096);
		kprintf("%d ",p[i]);
    }
	kprintf("\n");
    
    syssleep(4000);

    msg = "10000";
    syssend(p[2], msg, 40);

    msg = "7000";
    syssend(p[1], msg, 40);

    msg = "20000";
    syssend(p[0], msg, 40);

    msg = "27000";
    syssend(p[3], msg, 40);
    
	i = sysrecv(&p[3], msg, 40);
    kprintf("Message status returned trying to receive from %d: %d\n", p[3], i);

    msg = "hello?";
    i = syssend(p[2], msg, 40);
    kprintf("Message status returned trying to send to %d: %d\n", p[2], i);
}

void zombietask() {
    int r, id;
    id = sysgetpid();
    unsigned int p = 0;
    char str[40];
    char *msg = str;
    kprintf("ID:%d I'm ALIIIIIIIVE!\n",id);
    syssleep(5000);
    r = sysrecv(&p, msg, 40);
	if(r>0)
    	kprintf("ID:%d Message received from root. I will sleep for %s\n",id,msg);
    else
		kprintf("Receive failed %d\n",r);
	r = atoi(msg);
    syssleep(r);
    kprintf("ID:%d Done sleeping. Exiting now...\n",id);
}
